package jus.aor.printing;

import java.io.IOException;
import java.lang.Thread.State;
import java.net.*;
import java.util.*;
import java.util.logging.Logger;

//import jus.aor.printing.Esclave.Slave;
import static jus.aor.printing.Notification.*;

/**
 * Représentation du serveur d'impression.
 *
 * @author Morat
 */
public class Server {

    /**
     * 1 second timeout for waiting replies
     */
    protected static final int TIMEOUT = 1000;
    protected static final int MAX_REPONSE_LEN = 1024;
    /**
     * la taille de la temporisation
     */
    protected int backlog = 10;
    /**
     * le port de mise en oeuvre du service
     */
    protected int port = 3000;
    /**
     * le nombre d'esclaves maximum du pool
     */
    protected int poolSize = 10;
    /**
     * le contrôle d'arret du serveur
     */
    protected boolean alive = false;
    /**
     * le logger du server
     */
    Logger log = Logger.getLogger("Jus.Aor.Printing.Server", "jus.aor.printing.Server");

    /**
     * Construction du server d'impression
     */
    public Server() {
        log.setLevel(Level.INFO_1);
        Spooler sp = new Spooler(2000);
    }

    /**
     * le master thread TCP.
     */
    private void runTCP() {
        try {
            Socket soc = null;
            ServerSocket serverTCPSoc = new ServerSocket(port, backlog);
            log.log(Level.INFO_1, "Server.TCP.Started", new Object[]{port, backlog});
            while (alive) {
                log.log(Level.INFO, "Server.TCP.Waiting");
                try {
                    //-----------------------------------------------------------------
                    System.out.println("\n-----------------------\n"
                            + " Attente client");
                    soc = serverTCPSoc.accept();    // on crée notre socket
                    System.out.print("Attente de notification");
                    Notification not = TCP.readProtocole(soc);  // On récupere la notification
                    System.out.println(" ->notification reçu");
                    System.out.print("Attente de JobKey");
                    JobKey job = TCP.readJobKey(soc);
                    System.out.println(" ->job reçu");
                    if (not == Notification.QUERY_PRINT) {
                        this.sp.run(); // on lance le spooler.
                        // on aquitte la bonne reception de la requete.
                        System.out.print("Envoi de l'aquittement.");
                        TCP.writeProtocole(soc, Notification.REPLY_PRINT_OK);
                        System.out.println(" ->aquittement envoyé ");
                    } else {
                        //Erreur de notification.
                        TCP.writeProtocole(soc, Notification.REPLY_UNKNOWN_NOTIFICATION);
                    }
                    System.out.print("Envoi de l'aquittement.");
                    TCP.writeJobKey(soc, job);// On renvoit le jobKey concerné.
                    System.out.println(" ->aquittement envoyé ");


                    //---------------------------------------------------------------
                } catch (SocketException e) {
                    // socket has been closed, master serverTCP will stop.
                } catch (ArrayIndexOutOfBoundsException e) {
                    TCP.writeProtocole(soc, REPLY_UNKNOWN_NOTIFICATION);
                } catch (Exception e) {
                    TCP.writeProtocole(soc, REPLY_UNKNOWN_ERROR);
                }
                {
                }
            }
            log.log(Level.INFO_1, "Server.TCP.Stopped");
            serverTCPSoc.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    protected void setBacklog(int backlog) {
        this.backlog = backlog;
    }

    protected void setport(int port) {
        this.port = port;
    }

    protected void setPoolSize(int poolSize) {
        this.poolSize = poolSize;
    }
    protected Spooler sp;

    public void start() {
        System.out.println("start");
        alive = true;
        this.runTCP();
        System.out.println("fin");
    }

    public void stop() {
        System.out.println("stop");
        alive = false;
        sp.stopping();
    }

    /**
     *
     * @param args
     */
    public static void main(String args[]) {
        ServerGUI serverGUI = new ServerGUI(new Server());
    }
}